#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
@ TODO :
  - CD 1/2
  - langue FR, EN, FR+EN 
  - integrer hachoir
  - deplacer le fichier
  - reload du file selector
  
"""

import sys, os, shutil, string

""" handle ini files """
from ConfigParser import ConfigParser

""" external lib to get infos from video files """
from hachoir_core.cmd_line import unicodeFilename
from hachoir_parser import createParser
from hachoir_metadata import extractMetadata


try:
	import pygtk
	pygtk.require("2.0")
except:
	pass
try:
	import gtk
  
except:
	sys.exit(1)


class TestGTK:

	"""  path to files """
	videos_path = None
	
	""" liste de videos trouvÃ©es """
	t_videos = []
	
	""" vidÃ©o selectionnÃ©e """
	o_video = None
  
	""" nom proposÃ© pour la vidÃ©o """
	d_video = None
  
	"""" widget qui contient la proposition de nom de film """
	w_video_name = None
  
	""" renommage des codecs """
	t_tr_codecs_videos = {'default' : 'DiVX',
					   'DivX v3 MPEG-4 Low-Motion' : 'DiV3'}
	
  
	""" renommage des codecs """
	t_tr_codecs_audios = {'default' : '',
					   'MPEG Layer 3' : ''}
  

	""" ConfigParser object """
	o_config = None

	def __init__(self):
		# load config object
		self.o_config = ConfigParser()
	  	self.o_config.read(['config.ini'])
	
	  	self.videos_path = self.o_config.get('general', 'files_path')
	  	
	  	
		# fenetre de l'appli	
		w = gtk.Window()
		w.set_title('Film renamer')
		w.set_border_width(10)
		
		if (w):
			w.connect("destroy", gtk.main_quit)
	
			# container principal
			main_box = gtk.VBox(False, 0)
			w.add(main_box)
			
			# libelle texte
			main_box.add(gtk.Label('Veuillez choisir une vidÃ©o')) 
		
			# remplit la boite de selection
			self.add_file_select(main_box)  
		   
			#
			# container des specificitÃ©s de fichier
			#
			hbox = gtk.HBox(False, 0)
			
			# ajoute la selection des codecs videos
			self.add_videos_codecs_selector(hbox)
			
			# ajoute la selection des codecs audio
			self.add_audios_codecs_selector(hbox)
		
			# ajoute la selection de la qualitÃ©
			self.add_quality_selector(hbox)
		
			main_box.pack_start(hbox, True, True, 10)
			
			# ajoute la boite de proposition de nom de fichier
			self.w_video_name = gtk.Entry(256)
			self.w_video_name.set_name('inp_dest')
			main_box.add(self.w_video_name)
			
			# ajoute une boite de boutons
			self.add_actions(main_box)
			
			
			w.show_all()
			self.window = w
		
	"""
	extract and convert to list the value of an config entry.
	The entry must be delimited by comma
	"""
	def _get_list_from_config_key(self, key):
		return self.o_config.get('general', key).split(',')

	"""
	remplit le widget avec une sÃ©rie de radio
	"""
	def _fill_radio(self, label, config_key, handler, widget):
		f = gtk.Frame(label)
		vbox = gtk.VBox()
		vbox.set_border_with = 10
		f.add(vbox)
		  
		radio = None
		for codec in self._get_list_from_config_key(config_key):
			radio = gtk.RadioButton(radio, codec)
			radio.connect('toggled', handler)
			vbox.add(radio)
		widget.pack_start(f, True, True, 10)
  	
	"""
	ajoute la barre de boutons
	"""
	def add_actions(self, box):
		bbox = gtk.HButtonBox()
		bbox.set_border_width(5)
		bt_ok = gtk.Button(None, 'gtk-apply')
		bt_ok.connect('clicked', self.bt_ok_clicked) 
		bbox.add(bt_ok)
		bt_close = gtk.Button(None, 'gtk-close')
		bt_close.connect('clicked', gtk.main_quit)
		bbox.add(bt_close)
		
		box.add(bbox)
		
	

	
	"""
	ajout du groupe radio de selection des codecs videos
	"""
	def add_videos_codecs_selector(self, box):
		self._fill_radio('Codec vidÃ©o', 'video_codecs', self.hdl_video_codec, box)
	
	"""
	ajout du groupe radio de selection des codecs audio
	"""
	def add_audios_codecs_selector(self, box):
		self._fill_radio('Codec audio', 'audio_codecs', self.hdl_audio_codec, box)
  
	"""
	ajout du groupe radio de selection de la qualitÃ©
	"""
	def add_quality_selector(self, box):
		self._fill_radio('QualitÃ©', 'video_quality', self.hdl_quality, box)

	"""
	replissage du comboBox de sÃ©lection de fichier video
	"""
	def add_file_select(self, box):
	
		# on veut les videos
		self.retrieve_videos()
		
		combo = gtk.combo_box_new_text()
		for video in self.t_videos :
		  combo.append_text(video)
		
		combo.connect('changed', self.hdl_file_selected)  # ajout d'un signal...
		box.add(combo)

	"""
	recupÃ©ration des fichiers videos
	"""
	def retrieve_videos(self):
		files = os.listdir(self.videos_path) ## liste les fichiers du repertoire
		
		for file in files:
		  pathname = os.path.join(self.videos_path, file)
		  if os.path.isfile(pathname):
			t = file.rsplit('.', 1) ## path+fichier , extension
				   
			if len(t) < 2 : continue ## skip if no extension found ...   
				 
			if self._get_list_from_config_key('file_extensions').count(t[1]): ## filter only video extension
			  self.t_videos.append(file)


	def bt_ok_clicked(self, widget):

		if self.o_video :
			src = os.path.join(self.videos_path, self.o_video)
			dst = os.path.join(self.videos_path, self.w_video_name.get_text())
	  
			shutil.move(src, dst)
		  
		  # @TODO reload file selector ...
		  #	   clear selections
		  #	   raz input etc ....
		  #
	
	""" 
	handler de selection de la vidÃ©o 
	"""
	def hdl_file_selected(self, widget):
		self.o_video = widget.get_active_text()
		self.upd_dest_video()
	
	"""
	handler de selection du codec video 
	"""
	def hdl_video_codec(self, widget):
		if widget.get_active():
			self.codec_video = widget.get_label()
		  
		self.upd_dest_video()
	
	"""
	handler de selection du codec audio 
	"""
	def hdl_audio_codec(self, widget):
		if widget.get_active():
			self.codec_audio = widget.get_label()
	  
		self.upd_dest_video()
	
	"""
	handler de selection de la qualitÃ©
	"""
	def hdl_quality(self, widget):
		if widget.get_active():
			self.quality = widget.get_label()
	  
		self.upd_dest_video()
	
  
	def displayTree(self, parent):
		for field in parent:
			print "%s : %s " % (field.path, field.display)
		  
			if field.is_field_set : self.displayTree(field)


	"""
	renvoit le nb de stream
	"""
	def _get_nb_streams(self, parser):
		# nb de stream dans le flux si AVI
		if 'headers/avi_hdr/nb_stream' in parser:
			return string.atoi(parser['headers/avi_hdr/nb_stream'].display)
		return 0
	

	"""
	renvoit la stream video
	"""
	def _get_video_stream(self, parser):
		nb = self._get_nb_streams(parser)
		
		for i in range(0, nb):
			stream = '/headers/stream[%i]' % (i)
			stream_type = stream + '/stream_hdr/stream_type'
			if stream_type in parser and parser[stream_type].display == '"vids"':
				return parser[stream]
		  
	"""
	renvoit la stream audio
	"""
	def _get_audio_stream(self, parser):
		nb = self._get_nb_streams(parser)
		
		for i in range(0, nb):
			stream = '/headers/stream[%i]' % (i)
			stream_type = stream + '/stream_hdr/stream_type'
			if stream_type in parser and parser[stream_type].display == '"auds"':
				return parser[stream]
	  
	"""
	retourne le codec video
	"""
	def _find_video_codec(self, parser):
		"""
		/headers/avi_hdr/nb_stream
		/headers/stream[0]/stream_hdr/stream_type : "vids" 
		/headers/stream[0]/stream_hdr/fourcc : DivX v3 MPEG-4 Low-Motion 
		"""
		video = self._get_video_stream(parser)
		if 'stream_hdr/fourcc' in video:
			return video['stream_hdr/fourcc'].display

		return None

	"""
	traduit le codec video
	"""
	def _tr_video_codec(self, label):
		if label in self.t_tr_codecs_videos :
			return self.t_tr_codecs_videos[label]
		return self.t_tr_codecs_videos.default

	"""
	retourne le codec audio
	"""
	def _find_audio_codec(self, parser):
		"""
		/headers/avi_hdr/nb_stream
		/headers/stream[1]/stream_hdr/stream_type : "auds" 
		/headers/stream[1]/stream_fmt/codec : MPEG Layer 3 
		""" 
		audio = self._get_audio_stream(parser)
		if 'stream_fmt/codec' in audio:
			return self._tr_audio_codec(audio['stream_fmt/codec'].display)
		
		return None
  
	def _tr_audio_codec(self, label):
		"""
		"""
		if label in self.t_tr_codecs_audios :
			return self.t_tr_codecs_audios[label]
		return self.t_tr_codecs_audios.default

	"""
	analyse un fichier video
	"""
	def analyse_file(self):
		filename = unicodeFilename(os.path.join(self.videos_path, self.o_video))
		parser = createParser(filename)
		#metadata = extractMetadata(parser)
		
		print "codec video : %s " % self._find_video_codec(parser)
		print "codec audio : %s " % self._find_audio_codec(parser)
		return
	   	"""  
			for data in metadata:
				if not data.values:
					continue
				print data.description
				for item in data.values:
					print item.text
			return
		"""
		
		if not parser:
			print >>stderr, "Unable to parse file"
		return
	
		for field in parser:
		  if field.name == 'headers': self.displayTree(field) 
		#  print "%s: %s (size=%s bits) %s %s" % (field.absolute_address, field.name, field.size, field.description, field.display)

		
	"""
	met a jour le nom de destination de la vidÃ©o
	"""
	def upd_dest_video(self):
	
		if self.o_video == None: return

	  	""" il faut que le fichier existe """
		self.analyse_file()
	
		# 1 ..  separe le fichier de son extension
		t = self.o_video.lower().rsplit('.', 1)
		
		# 2 .. suppression des caractÃ¨res exotiques ...
		for pattern in self.o_config.get('general', 'symbols_to_exclude'):
			t[0] = t[0].replace(pattern, ' ')
		
		# 3 .. virer les accents .. @TODO	 
		
		# 4 .. camelcase 
		t[0] = string.capwords(t[0]).replace(' ', '.')
		
		self.d_video = t[0]+'-'+self.get_file_specs()+'.'+t[1] # @TODO : array.join() ???
		self.w_video_name.set_text(self.d_video)

	"""
	retourne une chaine correspondant aux spÃ©cifitÃ©s de la vidÃ©o
	"""
	def get_file_specs(self):

		s_ret = ''

		# handle codec video
		if self.codec_video :
			s_ret += self.codec_video

		# handle video quality
		if self.quality :
			s_ret += '.'+self.quality  

		# handle dec audio
		if(self.codec_audio and self.codec_audio != 'MP3') :
			s_ret += '.'+self.codec_audio

		return s_ret

if __name__ == "__main__":
	tg = TestGTK()
	gtk.main()
	